/*******************************************************************************
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
package com.example.slider.client.widget.slider;
import java.util.ArrayList;
import java.util.List;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArrayInteger;
import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONNumber;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.Widget;
/**
* This widget wraps the JQuery UI Slider
* and allows for single slider or double slider with range.
*
* All options can be get or set using generic get/setIntOption, get/setStringOption, get/setBooleanOption
* methods, but some convenience methods are provided for most popular such as
* setValues and setMinimum and setMaximum. See SliderOptions for full list of options.
* @see SliderOption
*/
public class Slider extends Widget
{
private JSONObject m_defaultOptions;
private List<SliderListener> m_listeners = new ArrayList<SliderListener>();
/**
* Create a slider with the specified ID. The ID is required
* because the slider needs a specific ID to connect to.
* @param id - id of the element
* @param min - default minimum of the slider
* @param max - default maximum of the slider
* @param defaultValue - default point of a single anchor
*/
public Slider(String id, int min, int max, int defaultValue)
{
this(id, min, max, new int[]{defaultValue});
}
/**
* Create a slider with the specified ID. The ID is required
* because the slider needs a specific ID to connect to.
* @param id - id of the element
* @param min - default minimum of the slider
* @param max - default maximum of the slider
* @param defaultValues - default points of each anchor
*/
public Slider(String id, int min, int max, int[] defaultValues)
{
this(id, getOptions(min, max, defaultValues));
}
/**
* Create the default slider with the specified ID. The ID is required
* because the slider needs a specific ID to connect to.
* @param id - id of the element to create
*/
public Slider(String id)
{
this(id, null);
}
/**
* Create a slider with the specified ID. The ID is required
* because the slider needs a specific ID to connect to.
* @param id - id of the element to create
* @param options - JSONObject of any possible option, can be null for defaults
*/
public Slider(String id, JSONObject options)
{
super();
Element divEle = DOM.createDiv();
setElement(divEle);
divEle.setId(id);
m_defaultOptions = options;
if (m_defaultOptions == null) {
m_defaultOptions = getOptions(0, 100, new int[]{0});
}
}
/**
* A convenient way to create an options JSONObject. Use SliderOption for keys.
* @param min - default minimum of the slider
* @param max - default maximum of the slider
* @param defaultValues - default points of each anchor
* @return a JSONObject of Slider options
*/
public static JSONObject getOptions(int min, int max, int[] defaultValues)
{
JSONObject options = new JSONObject();
options.put(SliderOption.MIN.toString(), new JSONNumber(min));
options.put(SliderOption.MAX.toString(), new JSONNumber(max));
JSONArray vals = intArrayToJSONArray(defaultValues);
options.put(SliderOption.VALUES.toString(), vals);
return options;
}
private static JSONArray intArrayToJSONArray(int[] values)
{
JSONArray vals = new JSONArray();
for (int i = 0, len = values.length; i < len; i++) {
vals.set(i, new JSONNumber(values[i]));
}
return vals;
}
@Override
protected void onLoad()
{
createSliderJS(this, getElement().getId(), m_defaultOptions.getJavaScriptObject());
super.onLoad();
}
@Override
protected void onUnload()
{
destroySliderJS(this, getElement().getId());
super.onUnload();
}
/**
* Gets the minimum possible value for the slider
* @return Returns the minimum.
*/
public int getMinimum()
{
return getIntOptionJS(getElement().getId(), SliderOption.MIN.toString());
}
/**
* Sets the minimum possible value for the slider
* @param minimum The minimum to set.
*/
public void setMinimum(int minimum)
{
setIntOptionJS(getElement().getId(), SliderOption.MIN.toString(), minimum);
}
/**
* Gets the maximum possible value for the slider
* @return Returns the maximum.
*/
public int getMaximum()
{
return getIntOptionJS(getElement().getId(), SliderOption.MAX.toString());
}
/**
* Sets the maximum possible value for the slider
* @param maximum The maximum to set.
*/
public void setMaximum(int maximum)
{
setIntOptionJS(getElement().getId(), SliderOption.MAX.toString(), maximum);
}
/**
* Convenience method for only 1 anchor
* @return Returns the value.
*/
public int getValue()
{
return getValueAtIndex(0);
}
/**
* Convenience method for only 1 anchor
* @param value to set.
*/
public void setValue(int value)
{
int[] values = {value};
setValues(values);
}
/**
* Sets the value of each anchor
* @param values - int array of values
*/
public void setValues(int[] values)
{
JSONArray vals = intArrayToJSONArray(values);
setValuesJS(getElement().getId(), vals.getJavaScriptObject());
}
/**
* Gets the value of a anchor at the specified index
*
* @param index the index to retreive the value for
*
* @return the value
*/
public int getValueAtIndex(int index)
{
return getValueJS(getElement().getId(), index);
}
/**
* Set an option numeric value
* @param option the SliderOption
* @param value the numeric
*/
public void setIntOption(SliderOption option, int value)
{
setIntOptionJS(getElement().getId(), option.toString(), value);
}
/**
* Get an option numeric value
* @param option the SliderOption
* @return value the numeric
*/
public int getIntOption(SliderOption option)
{
return getIntOptionJS(getElement().getId(), option.toString());
}
/**
* Set an option boolean value
* @param option the SliderOption
* @param value the boolean
*/
public void setBooleanOption(SliderOption option, boolean value)
{
setBooleanOptionJS(getElement().getId(), option.toString(), value);
}
/**
* Get an option boolean value
* @param option the SliderOption
* @return value the boolean
*/
public boolean getBooleanOption(SliderOption option)
{
return getBooleanOptionJS(getElement().getId(), option.toString());
}
/**
* Set an option string value
* @param option the SliderOption
* @param value the String
*/
public void setStringOption(SliderOption option, String value)
{
setStringOptionJS(getElement().getId(), option.toString(), value);
}
/**
* Set an option string value
* @param option the SliderOption
* @return value the String
*/
public String setStringOption(SliderOption option)
{
return getStringOptionJS(getElement().getId(), option.toString());
}
/**
* Add a SliderListener
* @param l - SliderListener
*/
public void addListener(SliderListener l)
{
m_listeners.add(l);
}
/**
* Removes the SliderListener
* @param l - SliderListener
*/
public void removeListener(SliderListener l)
{
m_listeners.remove(l);
}
private void fireOnStartEvent(Event evt, JsArrayInteger values)
{
int[] vals = jsArrayIntegerToIntArray(values);
SliderEvent e = new SliderEvent(evt, this, vals);
for (SliderListener l : m_listeners) {
l.onStart(e);
}
}
private boolean fireOnSlideEvent(Event evt, JsArrayInteger values)
{
int[] vals = jsArrayIntegerToIntArray(values);
SliderEvent e = new SliderEvent(evt, this, vals);
for (SliderListener l : m_listeners) {
l.onStart(e);
}
boolean ret = true;
for (SliderListener l : m_listeners) {
if (!l.onSlide(e)) {
//if any of the listeners returns false, return false,
//but let them all do their thing
ret = false;
}
}
return ret;
}
private void fireOnChangeEvent(Event evt, JsArrayInteger values, boolean hasOriginalEvent)
{
int[] vals = jsArrayIntegerToIntArray(values);
SliderEvent e = new SliderEvent(evt, this, vals, hasOriginalEvent);
for (SliderListener l : m_listeners) {
l.onChange(e);
}
}
private void fireOnStopEvent(Event evt, JsArrayInteger values)
{
int[] vals = jsArrayIntegerToIntArray(values);
SliderEvent e = new SliderEvent(evt, this, vals);
for (SliderListener l : m_listeners) {
l.onStop(e);
}
}
private int[] jsArrayIntegerToIntArray(JsArrayInteger values)
{
int len = values.length();
int[] vals = new int[len];
for (int i = 0; i < len; i++) {
vals[i] = values.get(i);
}
return vals;
}
/*
* JSNI methods
*/
private native void setIntOptionJS(String id, String option, int value) /*-{
$wnd.$("#" + id).slider("option", option, value);
}-*/;
private native int getIntOptionJS(String id, String option) /*-{
return $wnd.$("#" + id).slider("option", option);
}-*/;
private native void setBooleanOptionJS(String id, String option, boolean value) /*-{
$wnd.$("#" + id).slider("option", option, value);
}-*/;
private native boolean getBooleanOptionJS(String id, String option) /*-{
return $wnd.$("#" + id).slider("option", option);
}-*/;
private native void setStringOptionJS(String id, String option, String value) /*-{
$wnd.$("#" + id).slider("option", option, value);
}-*/;
private native String getStringOptionJS(String id, String option) /*-{
return $wnd.$("#" + id).slider("option", option);
}-*/;
private native void setValuesJS(String id, JavaScriptObject values) /*-{
$wnd.$("#" + id).slider("option", "values", values);
}-*/;
private native int getValueJS(String id, int index) /*-{
return $wnd.$("#" + id).slider("values", index);
}-*/;
private native void createSliderJS(Slider x, String id, JavaScriptObject options) /*-{
options.start = function(event, ui) {
x.@com.example.slider.client.widget.slider.Slider::fireOnStartEvent(Lcom/google/gwt/user/client/Event;Lcom/google/gwt/core/client/JsArrayInteger;)(event, ui.values);
};
options.slide = function(event, ui) {
return x.@com.example.slider.client.widget.slider.Slider::fireOnSlideEvent(Lcom/google/gwt/user/client/Event;Lcom/google/gwt/core/client/JsArrayInteger;)(event, ui.values);
};
options.change = function(event, ui) {
var has = event.originalEvent ? true : false;
x.@com.example.slider.client.widget.slider.Slider::fireOnChangeEvent(Lcom/google/gwt/user/client/Event;Lcom/google/gwt/core/client/JsArrayInteger;Z)(event, ui.values, has);
};
options.stop = function(event, ui) {
x.@com.example.slider.client.widget.slider.Slider::fireOnStopEvent(Lcom/google/gwt/user/client/Event;Lcom/google/gwt/core/client/JsArrayInteger;)(event, ui.values);
};
$wnd.$("#" + id).slider(options);
}-*/;
private native void destroySliderJS(Slider x, String id) /*-{
$wnd.$("#" + id).slider("destroy");
}-*/;
}